package site.zhouinfo.imageUtils;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;

/**
 * 图片操作工具
 *
 * @author zhou
 * @create 2017-03-29 16:32
 * @email zhouinfo@qq.com
 */
public class ImageUtil {
    /**
     * byte数组转ByteArrayInputStream
     */
    public static InputStream parseInputStream(byte[] data) {
        return new ByteArrayInputStream(data);
    }

    /**
     * byte数组转OutPutStream
     *
     * @throws IOException
     */
    public static OutputStream parseOutputStream(byte[] data) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        out.write(data);
        out.flush();
        return out;
    }

    /**
     * 根据比例重新生成图片
     * 图片的最大边长不会超过 size
     * 若图片最大边不超过size，则不修改图片大小
     */
    public static byte[] resizeImage(InputStream is, int size, String format) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(is);
        bis.mark(Integer.MAX_VALUE);
        BufferedImage prevImage = ImageIO.read(bis);
        bis.reset();
        double imageWidth = prevImage.getWidth();
        double imageHeight = prevImage.getHeight();

        int newWidth = 0;
        int newHeight = 0;

        if (imageHeight > size || imageWidth > size) {
            boolean isHeight = true;
            if (imageWidth > imageHeight) {
                isHeight = false;
            }
            double percent = 0;
            if (isHeight) {
                percent = size / imageHeight;
            } else {
                percent = size / imageWidth;
            }

            newWidth = (int) (imageWidth * percent);
            newHeight = (int) (imageHeight * percent);

        } else {
            newWidth = (int) imageWidth;
            newHeight = (int) imageHeight;
        }

        return resizeImage(bis, newHeight, newWidth, format);
    }


    /**
     * 重新调整图片大小，并返回调整后图片文件的byte数组
     */
    public static byte[] resizeImage(InputStream is, int height, int width, String format) throws IOException {
        BufferedImage prevImage = ImageIO.read(is);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics graphics = image.createGraphics();
        graphics.drawImage(prevImage, 0, 0, width, height, null);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(image, format, os);
        byte[] out = os.toByteArray();
        os.flush();
        os.close();
        return out;
    }


    /**
     * 判断文件是否为图片
     */
    public static boolean isImage(File imageFile) throws FileNotFoundException {
        FileInputStream fis = new FileInputStream(imageFile);
        boolean flag = isImage(fis);
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 判断文件是不是图片
     */
    public static boolean isImage(InputStream is) {
        Image img = null;
        try {
            img = ImageIO.read(is);
            if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) {
                return false;
            }
            return true;
        } catch (Exception e) {
            return false;
        } finally {
            img = null;
        }
    }


    /**
     * 获取图片文件格式
     */
    public static ImageFormat imageFormat(File file) throws FileNotFoundException {
        FileInputStream fis = new FileInputStream(file);
        ImageFormat imgfmt = imageFormat(fis);
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imgfmt;
    }


    /**
     * 获取图片文件的格式
     *
     * @throws IOException
     */
    public static ImageFormat imageFormat(InputStream is) {
        byte[] b = new byte[10];
        int l = -1;

        try {
            l = is.read(b);
        } catch (IOException e) {
            return ImageFormat.UNKNOW;
        }
        if (l == 10) {
            byte b0 = b[0];
            byte b1 = b[1];
            byte b2 = b[2];
            byte b3 = b[3];
            byte b6 = b[6];
            byte b7 = b[7];
            byte b8 = b[8];
            byte b9 = b[9];
            if (b0 == (byte) 'G' && b1 == (byte) 'I' && b2 == (byte) 'F') {
                return ImageFormat.GIF;
            } else if (b1 == (byte) 'P' && b2 == (byte) 'N' && b3 == (byte) 'G') {
                return ImageFormat.PNG;
            } else if (b6 == (byte) 'J' && b7 == (byte) 'F' && b8 == (byte) 'I' && b9 == (byte) 'F') {
                return ImageFormat.JPEG;
            } else {
                return ImageFormat.UNKNOW;
            }
        } else {
            return ImageFormat.UNKNOW;
        }
    }

    /**
     * 图片文件读取
     *
     * @param srcImgPath :源图片路径
     * @return BufferedImage    :输出的压缩图片
     */
    private static BufferedImage InputImage(String srcImgPath) {
        BufferedImage srcImage = null;
        try {
            FileInputStream in = new FileInputStream(srcImgPath);
            srcImage = javax.imageio.ImageIO.read(in);
        } catch (IOException e) {
            System.out.println("读取图片文件出错！" + e.getMessage());
            e.printStackTrace();
        }
        return srcImage;
    }

    /**
     * 将图片按照指定的图片尺寸压缩
     *
     * @param srcImgPath :源图片路径
     * @param outImgPath :输出的压缩图片的路径
     * @param new_w      :压缩后的图片宽
     * @param new_h      :压缩后的图片高
     */
    public static void compressImage(String srcImgPath, String outImgPath, int new_w, int new_h) {
        BufferedImage src = InputImage(srcImgPath);
        OutImage(outImgPath, disposeImage(src, new_w, new_h));
    }

    /**
     * 指定长或者宽的最大值来压缩图片
     *
     * @param srcImgPath :源图片路径
     * @param outImgPath :输出的压缩图片的路径
     * @param maxLength  :长或者宽的最大值
     */
    public static void compressImage(String srcImgPath, String outImgPath, int maxLength) {
        OutImage(outImgPath, compressImage(srcImgPath, maxLength));
    }

    /**
     * 指定长或者宽的最大值来压缩图片
     *
     * @param srcImgPath :源图片路径
     * @param maxLength  :长或者宽的最大值
     */
    public static BufferedImage compressImage(String srcImgPath, int maxLength) {
        // 得到图片
        BufferedImage src = InputImage(srcImgPath);
        if (null != src) {
            int old_w = src.getWidth();
            // 得到源图宽
            int old_h = src.getHeight();
            // 得到源图长
            int new_w = 0;
            // 新图的宽
            int new_h = 0;
            // 新图的长
            // 根据图片尺寸压缩比得到新图的尺寸
            if (old_w > old_h) {
                // 图片要缩放的比例
                new_w = maxLength;
                new_h = (int) Math.round(old_h * ((float) maxLength / old_w));
            } else {
                new_w = (int) Math.round(old_w * ((float) maxLength / old_h));
                new_h = maxLength;
            }
            return disposeImage(src, new_w, new_h);
        }
        return null;
    }

    /**
     * 处理图片
     *
     * @param src   :源图片路径
     * @param new_w :压缩后的图片宽
     * @param new_h :压缩后的图片高
     */
    private synchronized static BufferedImage disposeImage(BufferedImage src, int new_w, int new_h) {
        // 得到图片
        int old_w = src.getWidth();
        // 得到源图宽
        int old_h = src.getHeight();
        // 得到源图长
        BufferedImage newImg = null;
        // 判断输入图片的类型
        switch (src.getType()) {
            case 13:
                // png,gifnewImg = new BufferedImage(new_w, new_h,
                // BufferedImage.TYPE_4BYTE_ABGR);
                break;
            default:
                newImg = new BufferedImage(new_w, new_h, BufferedImage.TYPE_INT_RGB);
                break;
        }
        Graphics2D g = newImg.createGraphics();
        // 从原图上取颜色绘制新图
        g.drawImage(src, 0, 0, old_w, old_h, null);
        g.dispose();
        // 根据图片尺寸压缩比得到新图的尺寸
        newImg.getGraphics().drawImage(src.getScaledInstance(new_w, new_h, Image.SCALE_SMOOTH), 0, 0, null);
        return newImg;
    }

    /**
     * 将图片文件输出到指定的路径，并可设定压缩质量
     *
     * @param outImgPath :输出的压缩图片的路径
     * @param newImg     :输出的压缩图片
     */
    private static void OutImage(String outImgPath, BufferedImage newImg) {
        // 判断输出的文件夹路径是否存在，不存在则创建
        File file = new File(outImgPath);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }// 输出到文件流
        try {
            ImageIO.write(newImg, outImgPath.substring(outImgPath
                    .lastIndexOf(".") + 1), new File(outImgPath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 图片的格式枚举
     * jpg，png，gif，三种图片的格式名，格式后缀，以及Http的Header：Content-Type信息
     */
    public enum ImageFormat {
        JPEG("jpg", ".jpg", "image/jpeg"),
        PNG("png", ".png", "image/png"),
        GIF("gif", ".gif", "image/gif"),
        UNKNOW("jpg", ".jpg", "image/jpeg");

        private String format;
        private String suffix;
        private String contentType;

        private ImageFormat(String format, String suffix, String contentType) {
            this.format = format;
            this.suffix = suffix;
            this.contentType = contentType;
        }

        public String getFormat() {
            return format;
        }

        public String getSuffix() {
            return suffix;
        }

        public String getContentType() {
            return contentType;
        }
    }
}
